<?xml version="1.0" encoding="UTF-8"?>
<doc>
<title>表达式和运算符</title>

<para>
<ptitle>表达式和运算符</ptitle>
　<kw>表达式</kw>是运算符和操作数(operand)的集合，或者是常量。<r/>
<r/>
　通常用以下格式书写。<r/>
<r/>
<tt>
	表达式;<r/>
</tt>
<r/>
　像这样在表达式的后面加上分号(;)的话，该表达式会被当场求值( = 执行 )，而产生的结果会被丢弃。<r/>
<r/>
<example>
	a = b;<r/>
	// 由于 = 运算符的作用，b变量 的值被代入到 a变量 中<r/>
<r/>
	func();<r/>
	// 由于 ( ) 运算符的作用，func 作为函数被调用，函数的返回值被舍弃<r/>
<r/>
	1 + 3;<r/>
	// 由于 + 运算符的作用，1 和 3 被求和，其结果被舍弃(实际上<r/>
	// 因为这个表达式没有意义，它不会被执行)<r/>
</example>
</para>

<para>
<ptitle>真(true) 和 假(false)</ptitle>
　有些运算符用于对真和假 (逻辑值) 进行处理。运算结果为 0 是代表 假(false) ，非0 是代表 真(true) 。<r/>
　对字符串判断真假的时候，空字符串为 假、字符串非空的时候会被尝试转换为数值。如果转换成功就以转换结果的数值来判断真假，转换不成功则认定为 假。<r/>
</para>

<para>
<ptitle>运算符</ptitle>
　下面以优先级由低到高的顺序对各个运算符以下进行说明。<r/>
</para>


<para>
<ptitle>if 运算符</ptitle>
　条件运算符 <tt>if</tt> 会对其右侧的表达式求值，如果结果为 真 ，就会对左侧的表达式求值。<r/>
<example>
	a=b if b!=0; // 如果 b 不为 0 则将 b 的值代入 a <r/>
</example>
<r/>
　该运算符并不返回运算结果。<r/>
</para>

<para>
<ptitle>顺序运算符</ptitle>
　顺序运算符 <tt><kw>,</kw></tt> (逗号) 会先对左侧的表达式求值，然后对右侧的表达式求值。除此以外什么都不做。右侧的表达式的结果会作为该运算符的执行结果。连续出现多个逗号的时候，会从左侧开始依次求值。<r/>
<example>
	c = (a=1, b=2); // 对 a=1, b=2 这两个表达式进行求值，后面的表达式的结果 2 会被带入 变量 c 中<r/>
	a=1, b=2, c=3; // 按照 a=1, b=2, c=3 的顺序依次求值<r/>
</example>
</para>

<para>
<ptitle>赋值运算符</ptitle>
　下面的这些就是赋值运算符。<r/>
<r/>
<tt><kw>=</kw>  <kw>&lt;-&gt;</kw>  <kw>&amp;=</kw>  <kw>|=</kw>  <kw>^=</kw>  <kw>-=</kw>  <kw>+=</kw>  <kw>%=</kw>  <kw>/=</kw>  <kw>\=</kw>  <kw>*=</kw>  <kw>||=</kw>  <kw>&amp;&amp;=</kw>  <kw>&gt;&gt;=</kw>  <kw>&lt;&lt;=</kw>  <kw>&gt;&gt;&gt;=</kw></tt>
<r/>
　其中， = 运算符是单纯的赋值运算符，其作用是，先对右侧的表达式求值，然后将求得的结果代入左边的变量。以右侧的表达式的值作为该运算符的运算结果。<r/>
<example>
	a = 0;  // 将 0 代入 变量 a <r/>
	a = b = c = 0; // 将 0 依次代入变量 c , b, a <r/>
</example>
<r/>
　<tt>&lt;-&gt;</tt> 运算符用来进行值的交换。首先对左侧的表达式求值，然后对右侧的表达式求值。在那之后，将右侧表达式的值代入左侧的变量，左侧表达式的值代入右侧的变量。该运算符不返回结果。<r/>
　就目前来讲，为了对运算符左侧和右侧的表达式分别求值和代入，两侧的表达式发生了<b>重复求值</b>的现象。以后这个方法可能会改变，所以请不要设计利用这一特征的算法。<r/>
<r/>
　除此之外的运算符都属于 <tt>运算符=</tt> 的形式，<tt>A 运算符= B</tt> 的写法相当于 <tt>A = A 运算符 B</tt> 。A 运算符 B 的结果就会作该运算符(运算符=)的结果。<r/>
</para>

<para>
<ptitle>条件运算符</ptitle>
　条件运算符 <tt><kw>? :</kw></tt> 是一个三目运算符。写成 <tt>A ? B : C</tt> 的形式的话，会先对 A表达式 求值。结果为真的时候会对 B表达式 求值，忽略 C表达式。结果为假的时候会对 C表达式 求值，忽略 B表达式。B表达式 和 C表达式 中被求值的那个表达式的值会作为该运算符的结果。<r/>
<r/>
　条件运算符可以作为左值使用。<r/>
<example>
	a = b==0 ? c : b; // 如果 b 等于 0 那么 将 c 代入 a ，如果 b 不等于 0 则将 b 代入 a <r/>
	b==0 ? (a=c) : (a=b); // 和上面的表达式具有相同的意义<r/>
	(a ? b : c ) = d; // 如果 a 为真，则将 d 代入 b ，如果a为假的话，则将 d 代入 c (作为左值使用的例子)<r/>
</example>
</para>

<para>
<ptitle>逻辑 或(OR) 运算符</ptitle>
　逻辑或运算符 <tt><kw>||</kw></tt> 会先对左侧的表达式求值，若结果为真，则忽略右侧的表达式，以“真”作为该运算符的结果。如果左侧表达式的结果为假，则对右侧的表达式进行求值，其结果(真或者假)作为该运算符的结果。<r/>
</para>

<para>
<ptitle>逻辑 与(AND) 运算符</ptitle>
　逻辑与运算符 <tt><kw>&amp;&amp;</kw></tt> 会先对左侧的表达式求值，如果结果为假，则忽略右侧的表达式，以“假”作为该运算符的结果。如果左侧的表达式的结果为真，则对右侧的表达式进行求值，其结果(真或者假)作为该运算符的结果。<r/>
</para>

<para>
<ptitle>按位 或(OR) 运算符</ptitle>
　按位或运算符 <tt><kw>|</kw></tt> 用于对每个 字位(bit) 进行逻辑或运算。先对左右两侧的表达式分别进行求值，将两个结果作为整数，按位逐个进行或运算，其结果作为该运算符的结果。(译者注：一个字节(byte)为8位，即包含8个字位(bit))<r/>
</para>

<para>
<ptitle>按位 异或(XOR) 运算符</ptitle>
　按位异或运算符 <tt><kw>^</kw></tt> 用于对每个 字位(bit) 进行逻辑异或运算。先对左右两侧的表达式分别进行求值，将两个结果作为整数，按位逐个进行异或运算，其结果作为该运算符的结果。<r/>
</para>

<para>
<ptitle>按位 与(AND) 运算符</ptitle>
　按位与运算符 <tt><kw>&amp;</kw></tt> 用于对每个 字位(bit) 进行逻辑与运算。先对左右两侧的表达式分别进行求值，将两个结果作为整数，按位逐个进行与运算，其结果作为该运算符的结果。<r/>
</para>

<para>
<ptitle>相等判断运算符</ptitle>
　<tt><kw>==</kw>  <kw>!=</kw>  <kw>===</kw>  <kw>!==</kw></tt>都属于相等判断运算符这一类。<r/>
<r/>
<dl>

<dt><tt>==</tt> 运算符</dt>
<dd><tt>==</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果两个表达式的结果一致则该运算符的结果为真，不一致则该运算符的结果为假。两侧表达式的结果的数据类型如果不相同，则会进行适当的转换后再进行比较。例如，<tt>-1 == '-1'</tt> 结果为真。</dd>

<dt><tt>!=</tt> 运算符</dt>
<dd><tt>!=</tt> 运算符就是把 <tt>==</tt> 运算符的结果进行真假互换。</dd>

<dt><tt>===</tt> 运算符</dt>
<dd><tt>===</tt> 运算符被称为 类型识别比较运算符，它与 <tt>==</tt> 运算符类似，区别在于它不会进行数据类型自动转换，数据类型不同即被判断为假。</dd>

<dt><tt>!==</tt> 运算符</dt>
<dd><tt>!==</tt> 运算符就是把 <tt>===</tt> 运算符的结果进行真假互换。</dd>
</dl>
</para>

<para>
<ptitle>比较运算符</ptitle>
　<tt><kw>&lt;</kw>  <kw>&gt;</kw>  <kw>&lt;=</kw>  <kw>&gt;=</kw></tt> 都属于比较运算符这一类。<r/>
<r/>
<dl>

<dt><tt>&lt;</tt> 运算符</dt>
<dd><tt>&lt;</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果左侧表达式的值小于右侧表达式的值，则运算符的结果为真，否则运算符的结果为假。</dd>

<dt><tt>&gt;</tt> 运算符</dt>
<dd><tt>&gt;</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果右侧表达式的值小于左侧表达式的值，则运算符的结果为真，否则运算符的结果为假。</dd>

<dt><tt>&lt;=</tt> 运算符</dt>
<dd><tt>&lt;=</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果左侧表达式的值小于或等于右侧表达式的值，则运算符的结果为真，否则运算符的结果为假。</dd>

<dt><tt>&gt;=</tt> 运算符</dt>
<dd><tt>&gt;=</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果右侧表达式的值小于或等于左侧表达式的值，则运算符的结果为真，否则运算符的结果为假。</dd>
</dl>
<r/>
　比较的双方都是字符串的时候，会按照宽字符的编码的顺序(通常是UNICODE)来进行比较。<r/>
</para>

<para>
<ptitle>按位 移位(shift) 运算符</ptitle>
　<tt><kw>&gt;&gt;</kw>  <kw>&lt;&lt;</kw>  <kw>&gt;&gt;&gt;</kw></tt>都属于按位移位运算符这一类。<r/>
<r/>
<dl>

<dt><tt>&gt;&gt;</tt> 运算符</dt>
<dd><tt>&gt;&gt;</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。将左侧表达式的结果作为整数，依照右侧表达式的结果所决定的次数进行向右的带符号位移，位移后的值作为该运算符的结果。</dd>

<dt><tt>&lt;&lt;</tt> 运算符</dt>
<dd><tt>&lt;&lt;</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。将左侧表达式的结果作为整数，依照右侧表达式的结果所决定的次数进行向左位移，位移后的值作为该运算符的结果。</dd>

<dt><tt>&gt;&gt;&gt;</tt> 运算符</dt>
<dd><tt>&gt;&gt;&gt;</tt> 运算符和<tt>&gt;&gt;</tt>运算符类似，区别在于它将左侧表达式的值作为无符号整数来进行处理。</dd>
</dl>
</para>

<para>
<ptitle>加减运算符</ptitle>
　<tt><kw>+</kw>  <kw>-</kw></tt> 分别为加法运算符和减法运算符。<r/>
<r/>
<dl>

<dt><tt>+</tt> 运算符</dt>
<dd><tt>+</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果两侧的结果都是数值，则将两边的结果相加，相加的结果作为该运算符的结果。如果某一侧，或者两侧的结果是字符串的时候，则两侧的结果都会作为字符串进行处理(其中数值或对象类型的数据如果能转换成字符串的话，会进行转换)，将右侧的结果字符串连接到左侧的结果字符串的后面，作为该运算符的结果。</dd>

<dt><tt>-</tt> 运算符</dt>
<dd><tt>-</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。把两侧的结果作为数值，从左侧的值中减去右侧的值，其结果作为该运算符的结果。</dd>
</dl>
</para>

<para>
<ptitle>乘除取余运算符</ptitle>
　<tt><kw>%</kw>  <kw>/</kw>  <kw>\</kw>  <kw>*</kw></tt> 分别为取余、除法、整除和乘法运算符。<r/>
<r/>
<dl>

<dt><tt>%</tt> 运算符</dt>
<dd><tt>%</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。之后，左侧的值除以右侧的值，所得的余数作为该运算符的结果。两侧表达式的值都作为整数来处理，结果也为整数。</dd>

<dt><tt>/</tt> 运算符</dt>
<dd><tt>/</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。之后，左侧的值除以右侧的值，其结果作为该运算符的结果。结果为实数。</dd>

<dt><tt>\</tt> 运算符</dt>
<dd><tt>\</tt> 运算符会像 / 那样进行除法运算，只不过结果为整数。</dd>

<dt><tt>*</tt> 运算符</dt>
<dd><tt>*</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。之后，左右两侧的值相乘作为该运算符的结果。结果为实数。</dd>
</dl>
</para>

<para>
<ptitle>普通的单目运算符</ptitle>
　下面的运算符都是单目运算符 ( <tt>instanceof</tt> 除外 )。<r/>
<r/>
<dl>

<dt><tt><kw>!</kw></tt> 运算符</dt>
<dd>前置的 <tt>!</tt> 运算符是逻辑 非(NOT) 运算符。将右侧的表达式的结果进行真假调换，作为该运算符的结果。</dd>

<dt><tt><kw>~</kw></tt> 运算符</dt>
<dd><tt>~</tt> 运算符是按位取反运算符。将右侧表达式的结果作为整数，逐位取反 ( 1→0、0→1 ) 将取反后的值作为该运算符的结果。</dd>

<dt><tt><kw>--</kw></tt> 运算符</dt>
<dd>前置的 <tt>--</tt> 运算符是前置<kw>递减</kw>运算符。将右侧表达式的值减1，减1之后的值作为该运算符的结果。</dd>

<dt><tt><kw>++</kw></tt> 运算符</dt>
<dd>前置的 <tt>++</tt> 运算符是前置<kw>递增</kw>运算符。将右侧表达式的值加1，加1之后的值作为该运算符的结果。</dd>

<dt><tt><kw>new</kw></tt> 运算符</dt>
<dd><tt>new</tt> 运算符右面的函数调用表达式并不会被作为函数调用，而是用来创建对象。</dd>

<dt><tt><kw>invalidate</kw> 运算符</tt></dt>
<dd><tt>invalidate</tt> 运算符会将右侧表达式的结果对象无效化。</dd>

<dt><tt><kw>isvalid</kw> 运算符</tt></dt>
<dd><tt>isvalid</tt> 运算符会先对右侧或者左侧的的表达式求值，如果得到的结果的对象是有效的，则该运算符的结果为真，如果是无效的，则该运算符的结果为假。该运算符放到操作数的前面或后面具有相同的效果。</dd>

<dt><tt><kw>delete</kw> 运算符</tt></dt>
<dd><tt>delete</tt> 运算符会将写在右侧的对象的成员或者全局变量删除。删除成功则返回 true、失败则返回 false 。(译者注：该运算符在删除对象成员或全局变量时，不会把对象成员或全局变量所指向的对象也删除掉。如果环境中还存在其他对那个对象的引用则那个对象将被保留。)</dd>

<dt><tt><kw>typeof</kw> 运算符</tt></dt>
<dd><tt>typeof</tt> 运算符会对右侧的表达式进行求值，随着结果的数据类型不同，会返回如下的字符串：void:"void"、整数:"Integer"、实数:"Real"、对象:"Object"、字符串:"String"、字节串:"Octet" 。但是，如果指定了某对象的成员，但是这个对象却是不存在的，就会返回 "undefined" 。</dd>

<dt><tt><kw>#</kw> 运算符</tt></dt>
<dd><tt>#</tt> 运算符会对右侧的表达式进行求值，将结果字符串的第一个字符的编码作为该运算符的结果。</dd>

<dt><tt><kw>$</kw> 运算符</tt></dt>
<dd><tt>$</tt> 运算符会对右侧的表达式进行求值，将结果作为字符编码，而把该字符编码对应的那个字符作为该运算符的结果。</dd>

<dt><tt><kw>+</kw> 运算符</tt></dt>
<dd>单目的 <tt><kw>+</kw></tt> 运算符会先对右侧的表达式进行求值。如果右侧的结果是实数或整数就什么都不做，否则就会尝试将其变换为实数或整数，最后的结果作为该运算符的结果。将字符转换为数值并且转换失败的时候并不会产生异常，而是返回0。如果右侧表达式的运算结果中有“包含小数点”这类实数特征的话，会尝试转换成实数，否则尝试转换成整数，如果是以0x、0b或0开头的字符串的话，分别按照16进制数、2进制数或8进制数来解析。</dd>

<dt><tt><kw>-</kw> 运算符</tt></dt>
<dd>单目的 <tt>-</tt> 运算符会对右侧的表达式进行求值，将结果作为数值，将正负号取反之后作为该运算符的结果。</dd>

<dt><tt><kw>&amp;</kw> 运算符</tt></dt>
<dd>单目的 <tt>&amp;</tt> 运算符可以把 对某对象的属性成员的操作(读或写) 在不导致属性中的 属性控制器(getter和setter) 被执行的情况下，转换为对该属性对象本身的操作。例如，propobj = &amp;obj.prop; 这样写的话，obj 的成员属性 prop 的读写处理函数不会被执行，指向属性成员 prop 的<kw>属性对象</kw>本身的引用会被代入到 propobj 变量中。如果该运算符的右侧不是对属性的操作的话，该运算符的行为是不确定的。</dd>

<dt><tt><kw>*</kw> 运算符</tt></dt>
<dd>单目的 <tt>*</tt> 运算符会导致该运算符右侧的属性对象的 读写处理函数 被执行。这个运算符的右侧必须是代表属性对象的表达式。例如，*propobj = 1; 这样写的话，作为属性对象的 propobj 的 setter 方法被调用，1 被代入。</dd>

<dt><tt><kw>instanceof</kw> 运算符</tt></dt>
<dd><tt>instanceof</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。如果右侧的字符串是某个类的名字，而左侧是这个类的实例，则该运算符返回 true ，否则返回 false 。</dd>
</dl>
</para>

<para>
<ptitle>函数调用，括号类，后置的递增和递减等等</ptitle>
<dl>

<dt><tt><kw>(  )</kw> 运算符</tt></dt>
<dd><tt>(  )</tt> 运算符用于运算优先级的变更，以及函数的调用。</dd>

<dt><tt><kw>[  ]</kw> 运算符</tt></dt>
<dd><tt>[  ]</tt> 运算符是 间接成员选择 运算符。<tt>A [ B ]</tt> 这么写的话，会先对 A 求值，然后对 B 求值。将 B 作为字符串，在 A 中查找对应的成员名，并对那个成员进行操作。作为左值使用的时候，对象内的成员 B 如果不存在的话，会被创建。</dd>

<dt><tt><kw>.</kw> 运算符</tt></dt>
<dd><tt>.</tt> 运算符是 直接成员选择 运算符。<tt>A.B</tt> 这么写的话，会先对 A 求值。在 A 中查找 B 并对找到的成员进行操作。作为左值使用的时候，对象内的成员 B 如果不存在的话，会被创建。<r/>如果省略 <tt>.</tt> 运算符左侧的表达式，在 with 语句的范围外的话会被当作 global 对象的成员，在 with 语句内侧则会被当作 with 所指定的对象的成员。</dd>

<dt><tt><kw>++</kw> 运算符</tt></dt>
<dd>后置的 <tt>++</tt> 运算符是后置的递增运算符。将左侧的表达式加1，加1之前的左侧的表达式的值作为该运算符的结果。</dd>

<dt><tt><kw>--</kw> 运算符</tt></dt>
<dd>后置的 <tt>--</tt> 运算符是后置的递减运算符。将左侧的表达式减1，减1之前的左侧的表达式的值作为该运算符的结果。</dd>

<dt><tt><kw>!</kw> 运算符</tt></dt>
<dd>后置的 <tt>!</tt> 运算符是 表达式求值运算符。对左侧表达式求值，其结果作为字符串，被当作表达式字符串来解析。那个表达式字符串被解析并求值的结果作为该运算符的结果。解析出的表达式会在 this 上下文 (使用这个运算符的位置的 this) 中执行。</dd>

<dt><tt><kw>incontextof</kw> 运算符</tt></dt>
<dd><tt>incontextof</tt> 运算符会先对左侧表达式求值，然后对右侧表达式求值。将左侧表达式的结果作为对象，将这个对象的上下文部分替换为右侧表达式的结果，替换后的对象作为该运算符的结果。</dd>

<dt><tt><kw>int</kw> 运算符</tt></dt>
<dd>int 运算符会对右侧的表达式求值，将表达式的值转换为整数作为该运算符的结果。也可以像C语言那样写成 (int) 的形式。</dd>

<dt><tt><kw>real</kw> 运算符</tt></dt>
<dd>real 运算符会对右侧的表达式求值，将表达式的值转换为实数作为该运算符的结果。也可以像C语言那样写成 (real) 的形式。</dd>

<dt><tt><kw>string</kw> 运算符</tt></dt>
<dd>string 运算符会对右侧的表达式求值，将表达式的值转换为字符串作为该运算符的结果。也可以像C语言那样写成 (string) 的形式。</dd>
</dl>
</para>

</doc>
